#include <thread>
#include <iostream>

using namespace std;

/*
    使用RAII等待线程完成(join())
*/

struct func
{
private: 
        int& i;
public:
    func(int& i_) : i(i_) {}
    void operator() ()
    {
        for (unsigned j=0 ; j<1000000 ; ++j)
        {
            do_something(i);           // 1 潜在访问隐患：悬空引用
        }
    }
    void do_something(int &i){
        if(i % 100 == 0)
            cout << i << endl;
    }
};

class thread_guard
{
private:
    std::thread& t;
public:
    explicit thread_guard(std::thread& t_):
        t(t_) {}

    ~thread_guard()
    {
        // join()只能对给定的std::thread调用一次
        if(t.joinable()) // 1
        {
            t.join();      // 2
        }
    }
    // 拷贝构造函数和拷贝赋值操作被标记为=delete
    // 是为了不让编译器自动生成它们。直接对一个对象进行拷贝或赋值是危险的，因为这可能会弄丢已经加入的线程。
    // 通过删除声明，任何尝试给thread_guard对象赋值的操作都会引发一个编译错误。
    // 可以为任意函数添加= delete说明符，添加后就说明这些函数是不能使用的。
    thread_guard(thread_guard const&)=delete;   // 3
    thread_guard& operator=(thread_guard const&)=delete;
};

void do_something_in_current_thread(){
    cout << "do_something_in_current_thread" << endl;
}

void f()
{
    int some_local_state=0;
    func my_func(some_local_state);
    std::thread t(my_func);
    thread_guard g(t);
    do_something_in_current_thread();
}    // 当线程执行到此处时，栈中的局部对象就要被逆序销毁了(逆序调用构造函数)。

int main(){
    f();
    return 0;
}